<template>
  <div>
    <el-dialog title="修改素材信息" :visible.sync="editInfoVisible" width="500px" append-to-body>
      <el-form ref="form" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="名称" prop="imgName">
          <el-input v-model="form.imgName" placeholder="请输入图片名称" />
        </el-form-item>
        <el-form-item label="类别" prop="imgCategory">
          <el-input v-model="form.imgCategory" placeholder="请输入图片类别" />
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input v-model="form.remark" type="textarea" clearable :rows="2" placeholder="请输入备注" />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitInfo">确 定</el-button>
        <el-button @click="closeDialog">取 消</el-button>
      </div>
    </el-dialog>

    <el-dialog title="修改源文件" :visible.sync="editSourceVisible" width="600px" append-to-body>
      <el-upload
        ref="imgSourceUpload"
        :limit="1"
        action="#"
        drag
        accept=".psd, .tif, .cdr, .tiff, .ai, .psb"
        :disabled="isUploading"
        :on-change="editSourceChangeFile"
        :show-file-list="false"
        :auto-upload="false"
      >
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
        <div class="el-upload__tip text-left" slot="tip" v-if="uploadedFile">

          <div style="display: flex; align-items: center; justify-content: space-between;">
            <p style="font-weight: bold; font-size: 16px;">{{ uploadedFile.name }}</p>
            <el-tag v-if="uploadStatus === '0'" type="primary">读取完毕</el-tag>
            <el-tag v-if="uploadStatus === '1'" type="warning">压缩中，请稍后...</el-tag>
            <el-tag v-if="uploadStatus === '2'" type="warning">计算中，请稍后...</el-tag>
            <el-tag v-if="uploadStatus === '3'" type="danger">上传中</el-tag>
            <el-tag v-if="uploadStatus === '4'" type="success">上传完毕</el-tag>

          </div>
          <p style="display: flex; gap: 10px;">
            <span>文件大小: {{ $fileSize(uploadedFile.size) }}</span>
            <span>|</span>
            <span>HASH值: {{ uploadedFile.imgHash }}</span>
          </p>
          <el-progress v-if="uploadStatus === '3'" :percentage="uploadProgress" :color="customColors" />

        </div>
      </el-upload>

      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitSource" :disabled="uploadDisabled">确 定</el-button>
        <el-button @click="closeDialog">取 消</el-button>
      </div>
    </el-dialog>

    <el-dialog title="修改JPG文件" :visible.sync="editJpgVisible" width="600px" append-to-body>
      <el-upload
        ref="imgJpgUpload"
        :limit="1"
        action="#"
        drag
        accept=".jpg"
        :disabled="isUploading"
        :on-change="editJPGChangeFile"
        :show-file-list="false"
        :auto-upload="false"
      >
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
        <div class="el-upload__tip text-left" slot="tip" v-if="uploadedFile">

          <div style="display: flex; align-items: center; justify-content: space-between;">
            <p style="font-weight: bold; font-size: 16px;">{{ uploadedFile.name }}</p>
            <el-tag v-if="uploadStatus === '0'" type="primary">读取完毕</el-tag>
            <el-tag v-if="uploadStatus === '1'" type="warning">压缩中，请稍后...</el-tag>
            <el-tag v-if="uploadStatus === '2'" type="warning">计算中，请稍后...</el-tag>
            <el-tag v-if="uploadStatus === '3'" type="danger">上传中</el-tag>
            <el-tag v-if="uploadStatus === '4'" type="success">上传完毕</el-tag>

          </div>
          <p style="display: flex; gap: 10px;">
            <span>文件大小: {{ $fileSize(uploadedFile.size) }}</span>
            <span>|</span>
            <span>HASH值: {{ uploadedFile.imgHash }}</span>
          </p>
          <el-progress v-if="uploadStatus === '3'" :percentage="uploadProgress" :color="customColors" />

        </div>
      </el-upload>

      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitJpg" :disabled="uploadDisabled">确 定</el-button>
        <el-button @click="closeDialog">取 消</el-button>
      </div>
    </el-dialog>

    <el-dialog title="修改PNG文件" :visible.sync="editPngVisible" width="600px" append-to-body>
      <el-upload
        ref="imgPngUpload"
        :limit="1"
        action="#"
        drag
        accept=".png"
        :disabled="isUploading"
        :on-change="editPNGChangeFile"
        :show-file-list="false"
        :auto-upload="false"
      >
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
        <div class="el-upload__tip text-left" slot="tip" v-if="uploadedFile">

          <div style="display: flex; align-items: center; justify-content: space-between;">
            <p style="font-weight: bold; font-size: 16px;">{{ uploadedFile.name }}</p>
            <el-tag v-if="uploadStatus === '0'" type="primary">读取完毕</el-tag>
            <el-tag v-if="uploadStatus === '1'" type="warning">压缩中，请稍后...</el-tag>
            <el-tag v-if="uploadStatus === '2'" type="warning">计算中，请稍后...</el-tag>
            <el-tag v-if="uploadStatus === '3'" type="danger">上传中</el-tag>
            <el-tag v-if="uploadStatus === '4'" type="success">上传完毕</el-tag>

          </div>
          <p style="display: flex; gap: 10px;">
            <span>文件大小: {{ $fileSize(uploadedFile.size) }}</span>
            <span>|</span>
            <span>HASH值: {{ uploadedFile.imgHash }}</span>
          </p>
          <el-progress v-if="uploadStatus === '3'" :percentage="uploadProgress" :color="customColors" />

        </div>
      </el-upload>

      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitPng" :disabled="uploadDisabled">确 定</el-button>
        <el-button @click="closeDialog">取 消</el-button>
      </div>
    </el-dialog>

  </div>


</template>

<script>
import {getImgInfo, updateImgInfo} from "@/api/business/imgInfo";
import {MerkleTree} from "@/utils/MerkleTree";
import {getChunkUrl, mergeFile} from "@/api/tool/minio";
import axios from "axios";
import imageCompression from "browser-image-compression";

export default {
  name: "EditDialog",
  props: {
    visible: {
      type: Boolean,
      default: false,
    },
    id: {
      type: String,
      default: null
    },
    type: {
      type: String,
      default: 'info'
    }
  },
  data() {
    return {
      // 基本信息弹出框
      editInfoVisible: false,
      // 源文件弹出框
      editSourceVisible: false,
      // JPG文件弹出框
      editJpgVisible: false,
      // PNG文件弹出框
      editPngVisible: false,
      // 表单参数
      form: {},
      // 表单校验
      rules: {
        imgName: [
          { required: true, message: "图片名称不能为空", trigger: "blur" }
        ],
        imgSourcePath: [
          { required: true, message: "源图片路径不能为空", trigger: "blur" }
        ],
        imgJpgPath: [
          { required: true, message: "jpg图片路径不能为空", trigger: "blur" }
        ],
        imgPngPath: [
          { required: true, message: "png图片路径不能为空", trigger: "blur" }
        ],
      },
      // 源文件是否上传
      sourceUpload: false,
      jpgUpload: false,
      pngUpload: false,
      // 弹出框类型
      dialogType: null,
      // 存储上传的图片信息
      uploadedFile: null,
      // 上传状态
      uploadStatus: '0',
      // 进度条
      uploadProgress: 0,
      percentage: 0,
      isUploading: false,
      uploadDisabled: false,
      customColors: [
        { color: "#f56c6c", percentage: 20 },
        { color: "#e6a23c", percentage: 40 },
        { color: "#5cb87a", percentage: 60 },
        { color: "#1989fa", percentage: 80 },
        { color: "#6f7ad3", percentage: 100 },
      ],
    }
  },
  methods: {
    /** 接收父组件传来的值 */
    setIdAndType(id, type) {
      getImgInfo(id).then(response => {
        this.form = response.data;
        this[type === 'info' ? 'editInfoVisible' : `edit${type}Visible`] = true;
        this.uploadDisabled = type !== 'info';
      });
    },
    // 表单重置
    reset() {
      this.form = {
        id: null,
        imgName: null,
        imgCategory: null,
        imgSourcePath: null,
        imgJpgPath: null,
        imgPngPath: null,
        imgHash: null,
        imgSourceSize: null,
        imgJpgSize: null,
        imgPngSize: null,
        remark: null
      };
      this.$resetForm("form");
    },
    /** 弹窗关闭 */
    closeDialog() {
      this.editInfoVisible = false;
      this.editSourceVisible = false;
      this.editJpgVisible = false;
      this.editPngVisible = false;
      this.reset();
      this.uploadedFile = null; // 清空上传的文件
      this.uploadProgress = 0; // 重置进度条
      this.uploadStatus = '0'; // 重置上传状态
      this.isUploading = false; // 重置上传中状态
      this.uploadDisabled = false; // 重置按钮禁用状态
      // 检查并清空 el-upload 的文件列表
      if (this.$refs.imgSourceUpload) {
        this.$refs.imgSourceUpload.clearFiles();
      }
      if (this.$refs.imgJpgUpload) {
        this.$refs.imgJpgUpload.clearFiles();
      }
      if (this.$refs.imgPngUpload) {
        this.$refs.imgPngUpload.clearFiles();
      }

    },
    /** 提交基本信息表单 */
    submitInfo(){
      this.$refs.form.validate(valid => {
        if (valid) {
          updateImgInfo(this.form).then(response => {
            this.$modal.msgSuccess("修改基本信息成功");
            this.closeDialog();
            this.$emit('refreshTable');
          });
        }
      });
    },
    /** 提交表单 */
    async submitForm(type) {
      this.isUploading = true;
      this.uploadDisabled = true;

      if (type === 'Png') {
        this.uploadStatus = '2';
      }

      const file = this.uploadedFile.file.raw;
      // const file = this.$refs[`img${type}Upload`].uploadFiles[0].raw;
      const compressedFile = type === 'Png' ? await this.compressImage(file, 1024 * 1024) : file;
      const { hash, chunks } = await this.getFileMd5(compressedFile);
      this.uploadedFile.imgHash = hash;

      const res = await getChunkUrl(chunks.length, file.name, this.form[`img${type}Path`], file.type);
      const { parts, uploadId, filePath } = res.data;
      this.uploadStatus = '3';

      for (let i = 0; i < parts.length; i++) {
        await this.uploadFilePear(parts[i].uploadUrl, chunks[i], file.type, parts[i].parkNum, parts.length, file.uid);
      }

      await this.completeChunkFile(chunks.length, file.name, file.type, uploadId, hash, filePath);
      this.uploadStatus = '4';
      this.uploadProgress = 100;

      this.form = {
        ...this.form,
        [`img${type}Path`]: filePath,
        'flag': type === 'Png' ? 'UPDATE': '',
        [`img${type}Size`]: compressedFile.size,
        imgHash: hash,
      };

      updateImgInfo(this.form).then(response => {
        this.$modal.msgSuccess(`修改${type.toUpperCase()}文件成功`);
        this.closeDialog();
        this.$emit('refreshTable');
      });
    },
    /** 修改文件时触发 */
    editFileChange(file) {
      if (this.validateFile(file)) {
        this.uploadDisabled = false;
        this.uploadedFile = {
            name: file.name,
            size: file.size,
            imgHash: '',
            file: file
        };
      }
    },
    /** 公共文件验证逻辑 */
    validateFile(file) {
      if (!file || !file.raw || !(file.raw instanceof File)) {
        this.$modal.msgError("无效的文件信息，请重新选择文件。");
        return false;
      }

      const validSize = Number(file.size);
      if (isNaN(validSize) || !isFinite(validSize)) {
        this.$modal.msgError("文件大小不合法，请确认后重试。");
        return false;
      }
      return true;
    },
    /** 计算文件哈希值 */
    async getFileMd5(file) {
      const chunks = await this.$cutFile(file);
      const merkleTree = new MerkleTree(chunks.map((chunk) => chunk.hash));
      const md5 = merkleTree.getRootHash();
      const chunkFileList = chunks.map((chunk) => chunk.blob);
      return { hash: md5, chunks: chunkFileList };
    },
    /** 分片上传文件 */
    async uploadFilePear(url, file, contentType, partNum, totalParts, uid) {
      try {
        await axios.put(url, file, { headers: { "Content-Type": contentType }});
        this.uploadProgress = Math.round((partNum / totalParts) * 100)
      } catch (error) {
        this.handleError(error, "分片上传失败，请重试。");
      }
    },
    /** 合并分片文件 */
    async completeChunkFile(chunkNum, fileName, contentType, uploadId, fileMd5, filePath) {
      try {
        await mergeFile(chunkNum, fileName, contentType, uploadId, fileMd5, filePath);
      } catch (error) {
        this.handleError(error, "文件合并失败，请重试。");
      }
    },
    /** 压缩图片 */
    async compressImage(file, maxSize) {
      const options = {
        maxSizeMB: maxSize / (1024 * 1024),
        useWebWorker: true,
        maxWidthOrHeight: 1920,
        fileType: "image/png",
      };

      try {
        return await imageCompression(file, options);
      } catch (error) {
        throw error;
      }
    },
    /** 提交源文件 */
    submitSource() {
      this.submitForm('Source');
    },
    /** 提交JPG文件 */
    submitJpg() {
      this.submitForm('Jpg');
    },
    /** 提交PNG文件 */
    submitPng() {
      this.submitForm('Png');
    },
    /** 修改源文件时触发 */
    editSourceChangeFile(file) {
      // 清空文件列表
      this.$refs.imgSourceUpload.clearFiles();
      this.editFileChange(file);
    },
    /** 修改JPG文件时触发 */
    editJPGChangeFile(file) {
      // 清空文件列表
      this.$refs.imgJpgUpload.clearFiles();
      this.editFileChange(file);
    },
    /** 修改PNG文件时触发 */
    editPNGChangeFile(file) {
      // 清空文件列表
      this.$refs.imgPngUpload.clearFiles();
      this.editFileChange(file);
    },
  },
}
</script>

<style scoped>
/deep/ .el-upload{
  width: 100%;
}
/deep/ .el-upload .el-upload-dragger{
  width: 100%;
}
</style>
